<?php

include_once 'AuthUser.class.php';
include_once 'UserRole.class.php';
include_once 'InputValidationException.class.php';
include_once 'DbConnection.class.php';

/**
 * User Handler class 
 *
 * @author [Ruchira Amarasinghe] [rtamarasinghe@gmail.com]
 */
class UserHandler {

    public function getUserFromArray($data) {
        $user = new AuthUser();
        $user->setUserName($data['uname']);
        $user->setTitle($data['tit']);
        $user->setFirstName($data['ufname']);
        $user->setLastName($data['usname']);
        $user->setNID($data['nid']);
        $user->setDesignation($data['des']);
        $user->setUnit($data['unid']);

        $user->setEmail($data['email']);
        $user->setMobile($data['mob']);
        $user->setOtherPhone($data['ono']);
        $user->setPassword($data['pass']);
        
        if (isset($data['status'])) {
            $user->setStatus($data['status']);
        }
        
        if (isset($data['user_role_id'])) {
            $user->setUserRoleId($data['user_role_id']);
        }
        
        if (isset($data['uid'])) {
            $user->setUserId($data['uid']);
        }
        

        return $user;
    }

    public function isUserNameInUse($userName) {

        $userExists = false;

        $pdo = DbConnection::getInstance()->conn;

        $sql = "SELECT COUNT(uid) FROM user WHERE uname = ? ";

        $query = $pdo->prepare($sql);
        $query->execute(array($userName));

        if ($query->fetchColumn() > 0) {
            $userExists = true;
        }

        return $userExists;
    }

    /**
     * Save User 
     * @param array $post post variables
     */
    public function registerUser($post, $captcha) {

        $user = $this->getUserFromArray($post);

        $defaultRole = $this->getUserRoleByName(UserRole::DATA_ENTRY_OPERATOR);
        $user->setUserRoleId($defaultRole->getId());        
        $user->setStatus(AuthUser::STATUS_PENDING_APPROVAL);
        
        $captchaInput = $post['secno'];

        if ($captchaInput != $captcha) {
            throw new InputValidationException('Wrong security no, please type it correctly;', 0, $user);
        }

        $pass = $post['pass'];
        $pass2 = $post['pass2'];

        if ($pass != $pass2) {
            throw new InputValidationException('Passwords do not match;', 0, $user);
        }

        if ($user->getUserName() == '' || $user->getPassword() == '' ||
                $user->getTitle() == '' || $user->getFirstName() == '' ||
                $user->getDesignation() == '' || $user->getUnit() == '') {

            throw new InputValidationException('Please enter all the required(*) information;', 0, $user);
        }

        $userName = $user->getUserName();
        if ($this->isUserNameInUse($userName)) {
            throw new InputValidationException("'$userName' already used. Select another login name.", 0, $user);
        }

        return $this->saveUser($user);
    }

    public function saveUser(AuthUser $user) {
        $pdo = DbConnection::getInstance()->conn;

        $rip = $_SERVER['REMOTE_ADDR'];
        $rt = time();

        $sql = "INSERT INTO user " .
                "(uname, pass, tit, tit1, ufname, ufname1, usname, usname1, nid, " .
                " des, des1, unid, unid1, email, mob, ono, rt, rip, user_role_id) VALUES " .
                "(:userName, :password, :title, :title, :firstName, :firstName, :lastName, :lastName, :nid, " .
                " :desig, :desig, :unit, :unit, :email, :mobile, :otherPhone, :requestTime, :requestIp, :userRoleId)";

        $params = array(
            ':userName' => $user->getUserName(),
            ':password' => md5($user->getPassword()),
            ':title' => $user->getTitle(),
            ':firstName' => $user->getFirstName(),
            ':lastName' => $user->getLastName(),
            ':nid' => $user->getNid(),
            ':desig' => $user->getDesignation(),
            ':unit' => $user->getUnit(),
            ':email' => $user->getEmail(),
            ':mobile' => $user->getMobile(),
            ':otherPhone' => $user->getOtherPhone(),
            ':requestTime' => $rt,
            ':requestIp' => $rip,
            ':userRoleId' => $user->getUserRoleId()
        );

        $query = $pdo->prepare($sql);
        $result = $query->execute($params);

        if ($result === false) {
            throw new DbException('Error when saving user', 0, $sql, $params);
        }
        return $user;
    }

    public function getUsersByStatus($status) {
        
        $questionmarks = str_repeat("?,", count($status)-1) . "?";
        $sql = "SELECT * FROM user WHERE status IN (" . $questionmarks . ") ORDER BY ufname ASC";

        $params = $status;
        $roles = $this->getUsers($sql, $params);
        
        return $roles;
    }   
    

    public function getUserRoleByName($roleName) {
        $sql = "SELECT * FROM user_role WHERE name = :name";
        $params = array(':name' => $roleName);
        $roles = $this->getUserRoles($sql, $params);
        
        if (count($roles) == 0) {        
            throw new BaseException('Userrole with name ' . $roleName . ' . does not exist');
        }
        
        return $roles[0];
    }
    
    public function getUserRoleById($id) {
        $sql = "SELECT * FROM user_role WHERE id = :id";
        $params = array(':id' => $id);

        $roles = $this->getUserRoles($sql, $params);
        
        if (count($roles) == 0) {        
            throw new BaseException('Userrole with id ' . $id . ' . does not exist');
        }
        
        return $roles[0];
    }
    
    protected function getUserRoles($sql, $params) {
        
        $userRoles = array();
        
        $pdo = DbConnection::getInstance()->conn;
 
        $query = $pdo->prepare($sql);
        $result = $query->execute($params);

        if ($result === false) {
            throw new DbException('Error when fetching user roles', 0, $sql, $params);
        }
        
        do {
            $userRole = $query->fetchObject('UserRole');
            if ($userRole !== false) {
                $userRoles[] = $userRole; 
            }
        } while ($userRole !== false);

        return $userRoles;        
    }
    
    protected function getUsers($sql, $params) {
        
        $users = array();
        
        $pdo = DbConnection::getInstance()->conn;
 
        $query = $pdo->prepare($sql);
        $result = $query->execute($params);

        if ($result === false) {
            throw new DbException('Error when fetching users', 0, $sql, $params);
        }
        
        do {
            $data = $query->fetch();
            $user = $this->getUserFromArray($data);
            if ($data !== false) {
                $users[] = $user; 
            }
        } while ($data !== false);

        return $users;        
    }
    
    public function changeStatus($userIds, $status) {
        $questionmarks = str_repeat("?,", count($status)-1) . "?";        
        $sql = 'UPDATE user SET status = ? WHERE uid IN (' . $questionmarks . ')';
        $params = array($status);
        foreach ($userIds as $id) {
            $params[] = $id;
        }
        
        $pdo = DbConnection::getInstance()->conn;
        $query = $pdo->prepare($sql);
        $result = $query->execute($params);

        if ($result === false) {
            throw new DbException('Error when changing user status', 0, $sql, $params);
        }        
    }
    
    public function changeUserRole($userIds, $role) {
        $questionmarks = str_repeat("?,", count($userIds)-1) . "?";        
        $roleId = $role == UserRole::ADMIN ? 1 : 2;
        
        $sql = 'UPDATE user SET user_role_id = ? WHERE uid IN (' . $questionmarks . ')';
        $params = array($roleId);
        foreach ($userIds as $id) {
            $params[] = $id;
        }
        
        $pdo = DbConnection::getInstance()->conn;
        $query = $pdo->prepare($sql);
        $result = $query->execute($params);

        if ($result === false) {
            throw new DbException('Error when changing user role', 0, $sql, $params);
        }
    }

    public function saveUser1($post) {

        $searchParms = array();
        $searchParms = $this->getSearchParameters($post);

        if (count($searchParms) == 0)
            throw new Exception(" Please enter search parameters ");

        $pdo = DbConnection::getInstance()->conn;
        $params = array();
        $where = array();
        $sql = "SELECT * FROM pt  ";
        if (!empty($searchParms['id'])) {

            $whereHid = " hid LIKE ?  ";
            array_push($where, $whereHid);
            array_push($params, '%' . $searchParms['id'] . '%');
        }
        if (!empty($searchParms['name'])) {
            $whereName = " ( (CONCAT_WS(' ',fname,mname,sname) LIKE ? ) OR (fname LIKE ? OR mname LIKE ? OR sname LIKE ?) )";
            array_push($where, $whereName);
            array_push($params, '%' . $searchParms['name'] . '%');
            array_push($params, '%' . $searchParms['name'] . '%');
            array_push($params, '%' . $searchParms['name'] . '%');
            array_push($params, '%' . $searchParms['name'] . '%');
        }
        if (!empty($searchParms['sex'])) {

            $whereSex = " sex = ?";
            array_push($where, $whereSex);
            array_push($params, $searchParms['sex']);
        }
        if (count($where) > 0) {
            $sql .= " WHERE " . implode(" AND ", $where);
        }

        $query = $pdo->prepare($sql);
        $query->execute($params);

        return $query->fetchAll();
    }

}

